#include "vertexbuffer_directx9.h"
#include "indexbuffer_directx9.h"
#include "renderer_directx9.h"

namespace gecko
{

VertexBuffer_DirectX9::VertexBuffer_DirectX9()
{

}

VertexBuffer_DirectX9::~VertexBuffer_DirectX9()
{

}

bool VertexBuffer_DirectX9::Initialise(IRenderer* r, unsigned int vertexCount, bool dynamic)
{
	m_isSetup = false;
	m_vertexCount = vertexCount;
	m_vertexDeclaration = NULL;
	m_pVB = NULL;
	m_isSetup = false;
	m_indexBufferSet = false;
	m_d3dDevice = ((Renderer_DirectX9*)r)->GetD3DDevice();

	D3DVERTEXELEMENT9 vDecl[] =
	{
		{0, 0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
		{0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,    0},
		{0, 16, D3DDECLTYPE_FLOAT2,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
		D3DDECL_END()
	};

	HRESULT hr;

	hr = m_d3dDevice->CreateVertexDeclaration(vDecl, &m_vertexDeclaration);

	if ( FAILED(hr) )
	{
		Error("CreateVertexDeclaration() FAILED");
		return false;
	}

	m_dynamic = dynamic;
	D3DPOOL pool = dynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
	DWORD usage = dynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : D3DUSAGE_WRITEONLY; 

	hr = m_d3dDevice->CreateVertexBuffer(vertexCount * sizeof(Vertex), usage, 0, pool, &this->m_pVB, NULL);

	if ( FAILED(hr) )
	{
		Error("CreateVertexDeclaration() FAILED");
		return false;
	}

	return true;
}

bool VertexBuffer_DirectX9::Destroy()
{
	if ( m_pVB )
	{
		m_pVB->Release();
	}

	return true;
}

bool VertexBuffer_DirectX9::Lock(unsigned int offset, unsigned int vertexCount, Vertex** verts)
{
	Assert(m_pVB, "Vertex buffer is NULL");
	DWORD dwFlags = m_dynamic ? D3DLOCK_DISCARD : 0;
	if( FAILED(m_pVB->Lock(offset, vertexCount * sizeof(Vertex), (void**)verts, dwFlags)) )
	{
		return false;
	}

	return true;
}

bool VertexBuffer_DirectX9::Unlock()
{
	if ( FAILED(m_pVB->Unlock()) ) 
	{
		return false;
	}

	return true;
}

/*bool VertexBuffer_DirectX9::PreRender()
{
	gtAssert(Debug::MsgFilters::Renderer, m_d3dDevice, "Vertex buffer has not been initialised.");

	if ( FAILED(m_d3dDevice->SetStreamSource(0, this->m_pVB, 0, sizeof(Math::Vertex))) )
		return false;

	if ( FAILED(m_d3dDevice->SetVertexDeclaration(m_vertexDeclaration)) )
		return false;

	m_isSetup = true;

	return true;
}*/

bool VertexBuffer_DirectX9::SetIndexBuffer(IIndexBuffer* ib)
{
	Assert(m_d3dDevice, "Vertex buffer has not been initialised.");
	IndexBuffer_DirectX9 *dx9ib = (IndexBuffer_DirectX9*)ib;
	m_d3dDevice->SetIndices(dx9ib->m_pIB);
	m_indexBufferSet = true;

	return true;
}

bool VertexBuffer_DirectX9::Render(ePrimitiveType primitiveType, unsigned int primitiveCount)
{
	Assert(m_d3dDevice, "Vertex buffer has not been initialised.");

	if ( FAILED(m_d3dDevice->SetStreamSource(0, this->m_pVB, 0, sizeof(Vertex))) )
	{	
		return false;
	}

	if ( FAILED(m_d3dDevice->SetVertexDeclaration(m_vertexDeclaration)) )
	{
		return false;
	}

	if ( FAILED(m_d3dDevice->DrawPrimitive((D3DPRIMITIVETYPE)primitiveType, 0, primitiveCount)) )
	{
		return false;
	}

	return true;
}

bool VertexBuffer_DirectX9::RenderIndexed(ePrimitiveType primitiveType, unsigned int vertexCount, unsigned int primitiveCount)
{
	Assert(m_d3dDevice, "Vertex buffer has not been initialised.");
	//gtAssert(Debug::MsgFilters::Renderer, m_isSetup, "You must call preRender first.");

	if ( FAILED(m_d3dDevice->SetStreamSource(0, this->m_pVB, 0, sizeof(Vertex))) )
	{	
		return false;
	}

	if ( FAILED(m_d3dDevice->SetVertexDeclaration(m_vertexDeclaration)) )
	{
		return false;
	}

	if ( FAILED(m_d3dDevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primitiveType, 0, 0, vertexCount, 0, primitiveCount)) )
	{
		return false;
	}

	return true;
}

/*bool VertexBuffer_DirectX9::OnLostDevice()
{
	if ( m_dynamic )
	{
		if ( m_pVB )
		{
			m_pVB->Release();
			m_pVB = NULL;
		}
	}

	return true;
}

bool VertexBuffer_DirectX9::OnResetDevice()
{
	if ( m_dynamic )
	{
		D3DPOOL pool = D3DPOOL_DEFAULT;
		DWORD usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;

		if ( FAILED(m_d3dDevice->CreateVertexBuffer(m_vertexCount * sizeof(Math::Vertex), usage, 0, pool, &m_pVB, NULL)) )
		{
			return false;
		}
	}

	return true;
}*/

}
